package seedpod.kb2db;
/**
 * Copyright 2009 University of  Washington
 * This code is released under the GPL version 3 - with a copy of the license included
 * @author Maya Hao Li
 *
 */
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;

import seedpod.model.rdb.Rdb;
import seedpod.util.XMLWriter;
import edu.stanford.smi.protege.model.KnowledgeBase;
import edu.stanford.smi.protege.model.Project;

public class Application {
	/**
	 * @param args [path to the protege project] [database schema name] [destination directory]
	 */

	private static String GENERIC_OUTPUT_FILENAME = "generic.xml";
	private static String DATABASE_SCHEMA_OUTPUT = "postgresql.sql";
	private static String METADATA_OUTPUT = "metadata.sql";

	public static Protege2Rdb runTransform( KnowledgeBase kb, Rdb db ) {
		Protege2Rdb transformer = new Protege2Rdb( kb, db );
		transformer.validateKB();
		if ( !transformer.validateKB() ) {
			System.err.println( "invalid KB " );
			System.exit( -1 );
		}
		transformer.cleanup();
		transformer.transform();
		return transformer;
	}

	/**
	 * Application.main takes three arguments. 1) pprj file path, 2) project name, 3) output path
	 * 
	 * @param args
	 */
	@SuppressWarnings("unchecked")
	public static void main( String[] args ) {
		Collection protegeErrors = new ArrayList();
		String protegeProj, dbName, destDir;
		Project project;
		KnowledgeBase kb;
		Rdb db;
		Protege2Rdb transformer;

		if ( args.length < 1 ) {
			System.err.println( "must specify the knowledgebase to transform" );
			System.exit( -1 );
		}

		protegeProj = args[0];
		project = new Project( protegeProj, protegeErrors );

		if ( protegeErrors.size() == 0 ) {
			dbName = (args.length >= 2) ? args[1] : project.getName();
			destDir = (args.length >= 3) ? args[2] : null;

			kb = project.getKnowledgeBase();
			db = new Rdb( dbName );
			transformer = new Protege2Rdb( kb, db );
			transformer.validateKB();
			if ( !transformer.validateKB() ) {
				System.err.println( "invalid KB " );
				System.exit( -1 );
			}
			transformer.cleanup();
			transformer.transform();

			// save the project to "transform_[old project path]
			if ( protegeErrors.size() == 0 )
			{
				 project.save( protegeErrors );
			}

			if ( destDir == null )
				destDir = "kb2db_output\\" + project.getName();

			/** serialize the transformation result * */
			if ( destDir != null ) {
				try {
					FileOutputStream fo;
					File destDirFile = new File( destDir );
					if ( !destDirFile.exists() || !destDirFile.isDirectory() ) {
						destDirFile.mkdir();
					}

					 
					// generic xml output
					 File genericFile = new File( destDirFile, kb.getName() + "_" + GENERIC_OUTPUT_FILENAME );
					 System.out.println( "writing generic schema to " + genericFile.getAbsolutePath() );
					 fo = new FileOutputStream( genericFile );
					 PrintStream xml = new PrintStream( fo );
					 RdbXmlWriter xmlWriter = new RdbXmlWriter( db );
					 xmlWriter.serialize( xml );
					 xml.flush();
					 xml.close();

					// writing database schema
					File schemaFile = new File( destDirFile, kb.getName() + "_" + DATABASE_SCHEMA_OUTPUT );
					System.out.println( "writing postgrs schema to " + schemaFile.getAbsolutePath() );
					fo = new FileOutputStream( schemaFile );
					PrintStream sql = new PrintStream( fo );
					RdbSchemaWriter sqlWriter = new RdbSchemaWriter( db );
					sqlWriter.serialize( sql );
					sql.flush();
					sql.close();

					// write meta-data.sql to file
					File metaFile = new File( destDirFile, kb.getName() + "_" + METADATA_OUTPUT );
					System.out.println( "writing meta data to " + metaFile.getAbsolutePath() );
					fo = new FileOutputStream( metaFile );
					PrintWriter metaOut = new PrintWriter( new PrintStream( fo ) );
					ModelMap map = transformer.getMapping();
					map.serialize( metaOut );
					metaOut.flush();
					metaOut.close();

					Protege2Rdb.displayErrors( transformer.getTransformErrors(), "Error: " );
					Protege2Rdb.displayErrors( transformer.getTransformWarnings(), "Warning: " );
				}
				catch (IOException e) {
					e.printStackTrace();
				}
				 catch (XMLWriter.XMLException xe) {
					xe.printStackTrace();
				}
			} else
				System.err.println( "Destination directory does not exist. Writing output files aborted." );

		} else {
			Protege2Rdb.displayErrors( protegeErrors );
		}
	}
}
